Skip to content

feat(garm): drain resources before application removal - #312

Open
yanksyoon wants to merge 2 commits into
feat/isd-6082-cleanupfrom
feat/isd-6082-remove-hook
Open

feat(garm): drain resources before application removal#312
yanksyoon wants to merge 2 commits into
feat/isd-6082-cleanupfrom
feat/isd-6082-remove-hook

Conversation

@yanksyoon

Copy link
Copy Markdown
Member

Summary

  • Run GARM cleanup from the charm on.remove hook before application termination.
  • Refuse removal when admin credentials are unavailable.
  • Preserve idempotent cleanup and asynchronous drain behavior from the base PR.

Test plan

  • pytest -q tests/unit (238 passed)

Stacked on #311 and #310 as the final ISD-6082 slice.

Refs: ISD-6082

@florentianayuwono florentianayuwono left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thankyou!


cleanup_cls.assert_called_once_with(garm_api.auth_client)
cleanup_cls.return_value.run.assert_called_once_with()
assert out is not None

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a question, is there a way to assert the state, ie that the actual resource is removed, rather than just asserting that a method is called?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, that would be:

  1. write a fake client with internal state
  2. inject the fake client and assert the internal state after testing.

However, I think this isn't quite worth the effort here because we may end up testing the fake client's implementation.

Comment thread charms/garm/src/charm.py
self._reconcile,
)
self.framework.observe(self.on.update_status, self._reconcile)
self.framework.observe(self.on.remove, self._on_remove)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we add this removal flow to an existing integration test (if any)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, although I think we may have skipped that to reduce the cost of heavy integration test. If it doesn't exist, i'll test it via staging.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR wires the existing GARM resource-drain orchestration into the garm charm’s on.remove hook so that scalesets/runners are cleaned up before Juju removes the application, and removal is refused when admin credentials are unavailable.

Changes:

  • Observe on.remove and run GarmResourceCleanup using an authenticated local GARM API client.
  • Fail the remove hook when admin credentials are missing to avoid orphaning external resources.
  • Add Scenario unit tests covering the remove-hook cleanup invocation and the missing-credentials failure path.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
charms/garm/src/charm.py Adds on.remove observer and executes authenticated cleanup prior to charm removal; refuses removal when admin credentials aren’t available.
charms/garm/tests/unit/test_charm.py Adds unit tests asserting cleanup is invoked on remove and that removal fails without credentials.
Suppressed comments (1)

charms/garm/tests/unit/test_charm.py:514

  • This test’s docstring should follow the arrange/act/assert convention used throughout this file for readability and consistency.
def test_remove_refuses_without_admin_credentials(ctx: Context, garm_api: _GarmApiMocks):
    """Removal fails rather than orphaning resources when credentials are unavailable."""
    with pytest.raises(UncaughtCharmError, match="credentials are unavailable"):

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread charms/garm/tests/unit/test_charm.py Outdated
Comment on lines +502 to +503
def test_remove_runs_garm_cleanup_before_charm_termination(ctx: Context, garm_api: _GarmApiMocks):
"""Application removal drains GARM resources before the charm is removed."""
Comment thread charms/garm/src/charm.py
if not admin_creds:
raise RuntimeError("GARM admin credentials are unavailable; refusing removal")

base_url = f"http://127.0.0.1:{GARM_PORT}/api/v1"

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the base_url be a constant?

@yanksyoon
yanksyoon force-pushed the feat/isd-6082-remove-hook branch from a30f035 to cb0aca4 Compare August 19, 2026 04:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants